package vocoders;

import java.util.*;

public class RPE_LTP implements RPE_LTP_if {

	// Remove the CC component
	public void cc_filtering(double data[], double[] result) {
		result = new double[PRIMARY_FRAME_SIZE];
		for (int i = 0; i < PRIMARY_FRAME_SIZE - 1; i++)
			result[i] = (i == 0) ? (data[i])
					: (data[i] - data[i - 1] + ALPHA_OF * result[i - 1]);
	}

	// Pre-enhancement of high frequency components
	public void pe_filtering(double data[], double[] result) {
		result = new double[PRIMARY_FRAME_SIZE];
		for (int i = 0; i < PRIMARY_FRAME_SIZE - 1; i++)
			result[i] = (i == 0) ? (data[i])
					: (data[i] - BETA_PE * data[i - 1]);
	}

	// Autocorrelation of primary frames
	public void autocorr(double data[], double[] result) {
		result = new double[STP_ORDER + 1];
		for (int i = 0; i <= STP_ORDER; i++) {
			result[i] = 0;
			for (int j = 0; j <= PRIMARY_FRAME_SIZE; j++)
				result[i] += (j - i < 0) ? 0 : data[j] * data[j - i];
		}
	}

	// Schur's algorithm for determining the reflection coefficients
	public void schur_alg(double xcorr[], double[] gamma) {
		gamma = new double[STP_ORDER];
		double[] yf = new double[STP_ORDER + 1];
		double[] prev_yf = xcorr.clone();
		double[] yb = new double[STP_ORDER + 1];
		double[] prev_yb = xcorr.clone();

		for (int i = 1; i <= STP_ORDER; i++) {
			gamma[i - 1] = -prev_yf[i] / prev_yb[i - 1];
			for (int j = i + 1; j <= STP_ORDER; j++)
				yf[j] = prev_yf[j] + gamma[i - 1] * prev_yb[j - 1];
			for (int j = i + 1; j <= STP_ORDER; j++)
				yb[j] = gamma[i - 1] * prev_yf[j] + prev_yb[j - 1];
			prev_yf = yf.clone();
			prev_yb = yb.clone();
		}
	}

	// Computes the Log Area Ratios - this version might be slow because of the
	// log10 evaluation
	public void gamma2lar_basic(double[] gamma, double[] lar) {
		lar = new double[STP_ORDER];
		for (int i = 0; i < STP_ORDER - 1; i++)
			lar[i] = Math.log10((1 + gamma[i]) / (1 - gamma[i]));
	}

	// Computes the Log Area Ratios in a faster way but with less precision
	public void gamma2lar(double[] gamma, double[] lar) {
		lar = new double[STP_ORDER];
		double abs;
		for (int i = 0; i < STP_ORDER - 1; i++) {
			abs = Math.abs(gamma[i]);
			lar[i] = abs < 0.65 ? gamma[i]
					: (abs < 0.95 && abs >= 0.675) ? (2 * abs - 0.675 * Math
							.signum(gamma[i])) : (8 * abs - 6.375 * Math
							.signum(gamma[i]));
		}
	}

	// Encode LAR values
	public void lar_coding(double[] lar, int[] coded_lar) {
		coded_lar = new int[STP_ORDER];
		for (int i = 0; i < STP_ORDER - 1; i++)
			coded_lar[i] = Math.max((int) Math.min(
					Math.round(LARc_A[i] * lar[i] + LARc_B[i]), LARc_max[i]),
					LARc_min[i]);
	}

	// Decode LAR values
	public void lar_decoding(int[] coded_lar, double[] decoded_lar) {
		decoded_lar = new double[STP_ORDER];
		for (int i = 0; i < STP_ORDER - 1; i++)
			decoded_lar[i] = (double) (coded_lar[i] - LARc_B[i])
					/ (double) LARc_A[i];
	}

	// Interpolate LAR values from the previous frame with the ones from the
	// current frame
	public void lar_interpolation(double[] prev_lar, double[] crt_lar) {
		for (int i = 0; i < 13; i++)
			crt_lar[i] = 0.75 * prev_lar[i] + 0.25 * crt_lar[i];
		for (int i = 13; i < 27; i++)
			crt_lar[i] = 0.50 * prev_lar[i] + 0.50 * crt_lar[i];
		for (int i = 27; i < 40; i++)
			crt_lar[i] = 0.25 * prev_lar[i] + 0.75 * crt_lar[i];
	}

	public void lar2gamma(double[] lar, double[] gamma) {
		gamma = new double[STP_ORDER];
		double abs;
		for (int i = 0; i < STP_ORDER - 1; i++) {
			abs = Math.abs(lar[i]);
			if (abs < 0.65)
				gamma[i] = lar[i];
			else if (abs < 1.225 && abs >= 0.65)
				gamma[i] = Math.signum(lar[i]) * (0.5 * lar[i] + 0.3375);
			else if (abs <= 1.625 && abs >= 1.225)
				gamma[i] = Math.signum(lar[i]) * (0.125 * abs + 0.796875);
		}
	}

	public void st_err_lattice_filter(double[] frame, double[] error_frame) {
	}

	public void ltp_params(double[] sframe, double[] result) {
	}

	public void ltp_coding(double[] ltp_prms, int[] result) {
	}

	public void ltp_decoding(int[] coded_ltp, double[] decoded_ltp) {
	}

	public void anti_aliasing_filter(double[] serrframe, double[] result) {
	}

	public void decimation(double serrframe, double[] result) {
	}

	public void rpe_indexing(double[] dserrframe, double[] rpe_params) {
	}

	public void apcm_quantization(double[] rpe_params, int[] coded_rpe_params) {
	}

	public void apcm_decoding(int[] coded_rpe_params,
			double[] decoded_rpe_params) {
	}

	public void rpe_grill_positioning(double[] decoded_rpe_params,
			double[] result) {
	}

}
